package com.android.demo.interpolator;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import org.apache.http.protocol.HTTP;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Service;
import android.content.Context;
import android.location.Location;
import android.location.LocationManager;
import android.telephony.TelephonyManager;
import android.telephony.gsm.GsmCellLocation;
import android.util.Log;

/**
 * <br>Title:TODO 定位功能类
 * <br>Description:TODO 根据 wifi 基站 gps 方式定位
 * <br>Author:hexy
 * <br>Date:2011-3-31上午11:55:19
 * 学习资料:
 * 
 */
public class LocManager {
	private GsmCellLocation mGsmCellLocation = null;
	private TelephonyManager mLocalTelephonyManager = null;
	private LocationManager mLocationManager;
	private String TAG = "LocManager";
	
	private String mlanguage = "zh_cn";	
	public String getLanguage() {
		return mlanguage;
	}
	public void setLanguage(String mlanguage) {
		this.mlanguage = mlanguage;
	}
	
	public class Result{
		public double latitude;
		public double longitude;
		public String country;
		public String countryCode;
		public String region;
		public String county;
		public String city;
		public String street;
		public String streetNumber;
		public String postalCode;
		public String accessToken;
		public double accuracy;
	}
	
	/**
	 * <br>Description:TODO get latitude and longitude
	 * 	        在这里先使用GPS定位方式获取location信息,如果获取不到就使用WIFI/基站方式获取:
	 * <br>Author:hexy
	 * <br>Date:2011-3-31上午11:54:46
	 * @param context
	 * @return
	 */
	public Result getLocationByGpsOrNet(Context context) {
		Result result = new Result();
		double latitude = 0.0, longitude = 0.0;
		// 获取经纬度
		mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
		
		// gps 定位
		if (mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
			Location location = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
			if (location != null) {
				latitude = location.getLatitude(); // 经度
				longitude = location.getLongitude(); // 纬度
			}
		}
		// 网络定位
		else {
//			LocationListener locationListener = new LocationListener() {
//				public void onLocationChanged(Location location) { // 当坐标改变时触发此函数，如果Provider传进相同的坐标，它就不会被触发
//					if (location != null) {
//						Log.i("SuperMap",
//								"Location changed : Lat: "
//										+ location.getLatitude() + " Lng: "
//										+ location.getLongitude());
//					}
//				}
//
//				public void onProviderDisabled(String provider) {
//					// Provider被disable时触发此函数，比如GPS被关闭
//				}
//
//				public void onProviderEnabled(String provider) {
//					// Provider被enable时触发此函数，比如GPS被打开
//				}
//
//				public void onStatusChanged(String provider, int status,
//						Bundle extras) {
//					// Provider的转态在可用、暂时不可用和无服务三个状态直接切换时触发此函数
//				}
//			};
//			mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,1000, 0, locationListener);
			Location location = mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
			if (location != null) {
				latitude = location.getLatitude(); // 经度
				longitude = location.getLongitude(); // 纬度
			}
		}
		result.latitude = latitude;
		result.longitude = longitude;
		return result;
	}
	
	/**
	 * <br>Description:TODO 利用基站定位获取 中文详细路径信息
	 * <br>Author:hexy
	 * <br>Date:2011-3-31上午11:49:54
	 * @param context
	 * @return
	 */
	public Result getLocationByCellidWithGoogleApi(Context context){
		Result result = null;
		// get GsmCellLocation
		if (mLocalTelephonyManager==null || mGsmCellLocation == null) {
			mLocalTelephonyManager = (TelephonyManager)context.getSystemService(Service.TELEPHONY_SERVICE);
			mGsmCellLocation = (GsmCellLocation)mLocalTelephonyManager.getCellLocation();
		}
		
		if (mLocalTelephonyManager==null || mGsmCellLocation == null){
			Log.e(TAG, "if (mLocalTelephonyManager==null || mGsmCellLocation == null)");
			return result;
		}
		
		// get params
		int cellId = mGsmCellLocation.getCid();
		int locationAreaCode = mGsmCellLocation.getLac();
		
		int mobileCountryCode = Integer.valueOf(mLocalTelephonyManager.getNetworkOperator().substring(0, 3)).intValue();
	    int mobileNetworkCode = Integer.valueOf(mLocalTelephonyManager.getNetworkOperator().substring(3, 5)).intValue();
		
	    // set params to json
	    JSONObject locationJsonInfo = new JSONObject();
		try {
			
			locationJsonInfo.put("version", "1.1.0");
			locationJsonInfo.put("host", "maps.google.com");
			locationJsonInfo.put("address_language", mlanguage);
			locationJsonInfo.put("request_address", true);
			
			JSONObject cellTowerJsonInfo = new JSONObject();
			cellTowerJsonInfo.put("cell_id", cellId);
			cellTowerJsonInfo.put("location_area_code", locationAreaCode);
			cellTowerJsonInfo.put("mobile_country_code", mobileCountryCode);
			cellTowerJsonInfo.put("mobile_network_code", mobileNetworkCode);
			
			JSONArray cellTowersJsonArray = new JSONArray();
			cellTowersJsonArray.put(cellTowerJsonInfo);
			
			locationJsonInfo.put("cell_towers", cellTowersJsonArray);
		}catch(JSONException e){
			Log.e(TAG, e.toString());
		}
		
		// doPost
		HttpResult httpResult = doPost(locationJsonInfo,"http://www.google.com/loc/json"); 
		String response = httpResult.response;
		
		if (httpResult.ret==200){
			result = new Result();
			try {
				// decode json to result
				
				JSONObject responseJson = new JSONObject(response);
				JSONObject locationJson = responseJson.getJSONObject("location");
				JSONObject addressJson = locationJson.getJSONObject("address");
				
				if (responseJson.has("access_token"))
					result.accessToken = responseJson.getString("access_token");
				if (locationJson.has("latitude"))
					result.latitude = locationJson.getDouble("latitude");
				if (locationJson.has("longitude"))
					result.longitude = locationJson.getDouble("longitude");
				if (locationJson.has("accuracy"))
					result.accuracy = locationJson.getDouble("accuracy");
				
				if (addressJson.has("country"))
					result.country = addressJson.getString("country");
				if (addressJson.has("country_code"))
					result.countryCode = addressJson.getString("country_code");
				if (addressJson.has("region"))
					result.region = addressJson.getString("region");
				if (addressJson.has("county"))
					result.county = addressJson.getString("county");
				if (addressJson.has("city"))
					result.city = addressJson.getString("city");
				if (addressJson.has("street"))
					result.street = addressJson.getString("street");
				if (addressJson.has("street_number"))
					result.streetNumber = addressJson.getString("street_number");
				if (addressJson.has("postal_code"))
					result.postalCode = addressJson.getString("postal_code");
				
			}catch(JSONException e){
				Log.e(TAG, e.toString());
			}
		}
		
		return result;
	}
	
	 

	/**
	 * <br>Description:TODO get two point's distance
	 * <br>Author:hexy
	 * <br>Date:2011-3-31上午11:08:51
	 * @param lat1
	 * @param lng1
	 * @param lat2
	 * @param lng2
	 * @return
	 */
	private static final double EARTH_RADIUS = 6378.137;
	private static double rad(double d) {
	   return d * Math.PI / 180.0;
	}
	public static double getDistance(double lat1, double lng1, double lat2, double lng2)
	{
	   double radLat1 = rad(lat1);
	   double radLat2 = rad(lat2);
	   double a = radLat1 - radLat2;
	   double b = rad(lng1) - rad(lng2);
	   double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a/2),2) + 
	    Math.cos(radLat1)*Math.cos(radLat2)*Math.pow(Math.sin(b/2),2)));
	   s = s * EARTH_RADIUS;
	   //s = Math.round(s * 10000) / 10000;
	   return s;
	}
	
	
	/**
	 * <br>Title:TODO get response 
	 * <br>Description:TODO get detail infomation from google api
	 * <br>Author:hexy
	 * <br>Date:2011-3-31上午11:53:07
	 */
	private class HttpResult{
		public int ret;
		public String response;
	}
	private HttpResult doPost(JSONObject c, String strURL) { 
     	BufferedReader in = null;  
     	HttpResult result = new HttpResult();
     	result.ret = 0;
     	
         try{  
         	// make a POST client
             HttpClient client = new DefaultHttpClient();  
             HttpPost request = new HttpPost(strURL);
             
             // get json string and pass to entigy
             HttpEntity entity;
             StringEntity s = new StringEntity(c.toString());
             s.setContentType(new BasicHeader(HTTP.ASCII, "application/json"));
             entity = s;
             request.setEntity(entity);
             
             // POST and get response code
             HttpResponse response = client.execute(request);  
             result.ret = response.getStatusLine().getStatusCode();
   
             // get response string 
             in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));     
             StringBuffer sb = new StringBuffer("");   
             String line = "";  
             String NL = System.getProperty("line.separator");  
             while((line = in.readLine()) != null){  
                 sb.append(line + NL);  
             }  
             in.close();  
             result.response = sb.toString();
             
             // record received byte count
//             HttpTransportListener.GetInstance().AddRcvCount(m_strResponse.getBytes("UTF-8").length);
   
         }catch(Exception e){  
             Log.e(TAG,e.toString());
         }finally{
             if(in != null){  
                 try{  
                     in.close();  
                 }catch(IOException ioe){  
                     Log.e(TAG, ioe.toString());  
                 }  
             }  
         }
         
         return result;
     }
/** eg json google api
 * {
  "version": "1.1.0",
  "host": "maps.google.com",
  "home_mobile_country_code": 310,
  "home_mobile_network_code": 410,
  "radio_type": "gsm",
  "carrier": "Vodafone",
  "request_address": true,
  "address_language": "en_GB",
  "location": {
    "latitude": 51.0,
    "longitude": -0.1
  },
  "cell_towers": [
    {
      "cell_id": "42",
      "location_area_code": 415,
      "mobile_country_code": 310,
      "mobile_network_code": 410,
      "age": 0,
      "signal_strength": -60,
      "timing_advance": 5555
    },
    {
      "cell_id": "88",
      "location_area_code": 415,
      "mobile_country_code": 310,
      "mobile_network_code": 580,
      "age": 0,
      "signal_strength": -70,
      "timing_advance": 7777
    }
  ],
  "wifi_towers": [
    {
      "mac_address": "01-23-45-67-89-ab",
      "signal_strength": 8,
      "age": 0
    },
    {
      "mac_address": "01-23-45-67-89-ac",
      "signal_strength": 4,
      "age": 0
    }
  ]
}
*/
/**
{
	"location": {
	"latitude": 51,
	"longitude": -0.1,
	"address": {
	"country": "（大不列颠）联合王国",
	"country_code": "GB",
	"region": "西萨塞克斯郡",
	"county": "米德萨塞克斯",
	"city": "海沃兹希思",
	"street": "Fairford Close",
	"street_number": "12",
	"postal_code": "RH16 3"
	}
	},
	"access_token": "2:PE3h3VCCmxGFWHcx:t3E9VBazyijiWu5A"
	}
	
	<uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
	*/
}